-------------------------------------------------------------------------------
--
-- Title       : ALU
-- Design      : ALU
-- Author      : Microsoft
-- Company     : Microsoft
--
-------------------------------------------------------------------------------
--
-- File        : ALU.vhd
-- Generated   : Tue Nov 22 14:02:19 2011
-- From        : interface description file
-- By          : Itf2Vhdl ver. 1.20
--
-------------------------------------------------------------------------------
--
-- Description : 
--
-------------------------------------------------------------------------------

--{{ Section below this comment is automatically maintained
--   and may be overwritten
--{entity {ALU} architecture {ALU}}
	
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use work.all;
use constants.all;

entity ALU is 
	port(
	instr:          in  AluOpType;  	--op-code of instruction to be carried out
	aIn :			in  std_logic_vector(31 downto 0);	--first Operand
	bIn :			in  std_logic_vector(31 downto 0);	--second Operand
	result:     	out std_logic_vector(31 downto 0);	--culculation result
	flagZero:      	out std_logic;	 			-- TO DO 
	flagNeg:        out std_logic;	 			-- result is negative	 
	flagOverflow:	out std_logic);	
end ALU;

--}} End of automatically maintained section

architecture behave of ALU is	

signal a: signed (31 downto 0);		
signal b: signed (31 downto 0);


begin

	a <= signed(aIn);
	b <= signed(bIn);

	
	-- flagOverflow 	<= '1' when a(31) = '0' and b(31) = '0' and resVar(31) = '1' else '0';

	Instructions : process(a, b, aIn, bIn, instr)
	variable resVar: signed(31 downto 0);
	begin
		resVar := (others => '-');
		-- At the Beginning all signals have to be initialized
		flagNeg 	<= '0';
		flagOverflow 	<= '0';		
		
		case instr is
			
			when ALU_ADD => 
				resVar := a + b;
				-- wenn (a(31) = b(31) != resVar(31)) -> Vorzeichen ändern
				if((a(31) = b(31)) and (a(31) /= resVar(31))) then
					flagOverflow <= '1';
					resVar(31) := not(resVar(31)); 
				end if; 
				
			when ALU_SUB => 
				resVar 	:= (a - b);
				if((a(31) /= b(31)) and (a(31) /= resVar(31))) then	
					flagOverflow <= '1';
					resVar(31) := not(resVar(31)); -- wenn (a = b != resVar(31)) -> Vorzeichen �ndern
				end if;
										
			when ALU_PASS_B => 
				resVar := b;

			when ALU_AND =>
				resVar := (a and b);

			when ALU_OR =>
				resVar := (a or b);

			when ALU_NAND =>
				resVar := (a nand b);

			when ALU_XOR =>
				resVar := (a xor b);

			when ALU_NOT =>
				resVar := not b;

			-- Logical left Shift
			when ALU_SHIFT_L=>
				--resVar := a (30 downto 0) & '0';
				resVar := a sll to_integer(unsigned(bIn(4 downto 0)));

			-- Logical rigth Shift
			when ALU_SHIFT_R =>
				--resVar := '0' & a(31 downto 1);
				resVar := a srl to_integer(unsigned(bIn(4 downto 0)));

			-- Arithmetical Shift
			when ALU_SHIFT_A =>
				resVar := a(31) & a(31 downto 1);

			-- 2er Complement of a
			when ALU_NEG =>
				resVar := -b;
		   
			when ALU_SWAP16 =>
				resVar(15 downto 0) := b(31 downto 16);
				resVar(31 downto 16) := b(15 downto 0);
				
			when ALU_SWAP8 => 
				resVar(15 downto 8) := b(7 downto 0);
				resVar(7 downto 0) := b(15 downto 8);
				
			when ALU_BYTE_SWAP =>
				resVar(31 downto 24) := b(7 downto 0);
				resVar(23 downto 16) := b(15 downto 8);
				resVar(15 downto 8) := b(23 downto 16);
				resVar(7 downto 0) := b(31 downto 24);
				
			--when iROT_R =>
			--	resVar <= (a ror '1');
				
			--when iROT_L =>
			--	resVar <= (a rol '1');
			when others => 				
				-- in allen Faellen muss resVar zugewiesen sein, sonst wird daraus ein Latch
				-- das heisst aus dem Schaltnetz wird ein Schaltwerk
				resVar := (resVar'range => '0');
		end case;

		if resVar = (resVar'range => '0') then		
			flagZero <= '1';
		else
			flagZero <= '0';
		end if;
		
		flagNeg 	<= resVar(31);
		result 	  	<= std_logic_vector(resVar);	

	end process Instructions;				
	
end behave;
